home
diamond Go Premium
Data Engineering Path  ·  PySpark

Join Strategies

While specifying the type of join (Inner, Outer, etc.) determines the logical outcome, Spark must choose a physical join strategy to execute the join across the cluster. Understanding these physical strategies is critical to debugging performance bottlenecks and out-of-memory errors in Spark.


The Core Join Strategies

Spark uses three primary physical join strategies under the hood:

graph TD
    subgraph JoinStrategies["Spark Join Strategies"]
        direction TB
        SMJ["Sort-Merge Join (SMJ)<br>- Shuffles and sorts both datasets<br>- Standard for huge-to-huge tables"]
        BHJ["Broadcast Hash Join (BHJ)<br>- Broadcasts small table to all executors<br>- Fast, completely skips shuffles"]
        SHJ["Shuffle Hash Join<br>- Shuffles but doesn't sort<br>- Uses hash tables locally"]
    end
    style JoinStrategies fill:#eef2f6,stroke:#475569,stroke-width:2px;

1. Sort-Merge Join (SMJ)

  • The Default Strategy: Used when both joining datasets are large.
  • How it works:
    1. Shuffle Phase: Both tables are hashed and shuffled across the network based on the join key, ensuring rows with matching keys land in the same partition on the same executor.
    2. Sort Phase: Rows inside each partition are sorted by the join key.
    3. Merge Phase: The sorted partitions are joined by scanning through the records line-by-line (which is highly efficient since they are pre-sorted).
  • Performance Cost: Very High. Network shuffling and sorting are highly disk and CPU-intensive.

2. Broadcast Hash Join (BHJ)

  • The Speed King: Used when one of the joining tables is small (default threshold is 10 MB or less).
  • How it works:
    1. The small DataFrame is downloaded fully to the Driver node.
    2. The Driver broadcasts a copy of this small table as a hash map to all worker executors on the cluster.
    3. Each executor performs a fast local lookup join as it scans its own partition of the large table.
  • Performance Cost: Zero Shuffle! Network shuffles are completely avoided, converting wide dependencies into high-speed narrow dependencies.

3. Shuffle Hash Join

  • Similar to Sort-Merge, but it builds local hash tables on the partitions instead of sorting. Used when data is skewed or sorting cannot be done efficiently.

PySpark Code Example: Forcing a Broadcast Join

If you know a table is small (e.g. less than 100 MB), you can manually instruct Spark to broadcast it using pyspark.sql.functions.broadcast():

from pyspark.sql import SparkSession
from pyspark.sql.functions import broadcast, col

# 1. Setup Spark
spark = SparkSession.builder \
    .appName("Join Strategies") \
    .master("local[*]") \
    .getOrCreate()

# 2. Large Transactions DataFrame (Fact Table)
tx_data = [(101, 1, 500.0), (102, 2, 20.0), (103, 1, 150.0)]
tx_df = spark.createDataFrame(tx_data, ["tx_id", "user_id", "amount"])

# 3. Small Users DataFrame (Dimension Table - Less than 50MB)
users_data = [(1, "Alice"), (2, "Bob")]
users_df = spark.createDataFrame(users_data, ["user_id", "user_name"])

# 4. Perform Join forcing a Broadcast Join on users df
# This avoids shuffles on both datasets entirely!
broadcast_joined_df = tx_df.join(broadcast(users_df), "user_id", "inner")
broadcast_joined_df.show()

# 5. Inspect the Physical Execution Plan
# Look for 'BroadcastHashJoin' vs 'SortMergeJoin' in the output!
broadcast_joined_df.explain()
Find this content helpful? ☕ Buy me a coffee

Entity Details

Create New Item

celebration
Enjoying the free content?

Create a free account to track your progress and save your place.

Create Free Account
help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.